# -*- coding: utf-8 -*-
"""
Created on
@Time: 2024/12/23 8:18
@Author: Mr.Z
@contact: <QQ:40061980>
@contact: bob@pheks.com
@File: configPage.py
@IDE: PyCharm
@Python Version：
"""

import ftplib
import smtplib
import sqlite3
from datetime import datetime
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from Crypto.Random import get_random_bytes
from PySide6.QtWidgets import QWidget, QVBoxLayout, QFormLayout, QLineEdit, QGroupBox, QPushButton, QMessageBox

from utils.encrypt import encrypt_password, decrypt_password
from utils.log_recorder import setup_logger as logger
from database.connectSql import connect_sql
from database.database_setup import create_config_table


class ConfigPage(QWidget):
    """配置页面UI，用于配置接口、邮箱、FTP等信息"""

    def __init__(self, log_text_edit):
        super().__init__()
        self.log_text_edit = log_text_edit

        # 创建主布局
        main_layout = QVBoxLayout()

        # 创建接口配置组
        interface_group = QGroupBox("接口配置")
        interface_layout = QFormLayout()

        self.url_input = QLineEdit()
        self.url_input.setPlaceholderText("请输入Api URL")
        interface_layout.addRow("API URL:", self.url_input)

        self.appid_input = QLineEdit()
        self.appid_input.setPlaceholderText("请输入APP ID")
        interface_layout.addRow("APP ID:", self.appid_input)

        self.appkey_input = QLineEdit()
        self.appkey_input.setPlaceholderText("请输入APP KEY")
        self.appkey_input.setEchoMode(QLineEdit.Password)  # 设置为密码输入模式
        interface_layout.addRow("APP KEY:", self.appkey_input)

        interface_group.setLayout(interface_layout)
        main_layout.addWidget(interface_group)

        # 创建邮箱配置组
        email_group = QGroupBox("邮箱配置")
        email_layout = QFormLayout()

        self.from_email_input = QLineEdit()
        self.from_email_input.setPlaceholderText("请输入发件邮箱地址")
        email_layout.addRow("发件邮箱:", self.from_email_input)

        self.from_email_password_input = QLineEdit()
        self.from_email_password_input.setPlaceholderText("请输入发件邮箱密码或授权码")
        self.from_email_password_input.setEchoMode(QLineEdit.Password)  # 设置为密码输入模式
        email_layout.addRow("发件邮箱密码:", self.from_email_password_input)

        self.smtp_server_input = QLineEdit()
        self.smtp_server_input.setPlaceholderText("请输入SMTP服务器地址")
        email_layout.addRow("SMTP服务器:", self.smtp_server_input)

        self.smtp_port_input = QLineEdit()
        self.smtp_port_input.setPlaceholderText("请输入SMTP服务器的SSL端口")
        email_layout.addRow("SMTP端口:", self.smtp_port_input)

        self.to_email_input = QLineEdit()
        self.to_email_input.setPlaceholderText("请输入收件邮箱地址")
        email_layout.addRow("收件邮箱:", self.to_email_input)

        # 创建发送测试邮件按钮
        self.test_email_button = QPushButton("发送测试邮件")
        self.test_email_button.clicked.connect(self.test_email)
        email_layout.addRow("发件测试:", self.test_email_button)

        email_group.setLayout(email_layout)
        main_layout.addWidget(email_group)

        # 创建FTP配置组
        ftp_group = QGroupBox("FTP配置")
        ftp_layout = QFormLayout()

        self.ftp_host_input = QLineEdit()
        self.ftp_host_input.setPlaceholderText("请输入FTP主机地址")
        ftp_layout.addRow("FTP主机地址:", self.ftp_host_input)

        self.ftp_user_input = QLineEdit()
        self.ftp_user_input.setPlaceholderText("请输入FTP用户名")
        ftp_layout.addRow("FTP用户名:", self.ftp_user_input)

        self.ftp_password_input = QLineEdit()
        self.ftp_password_input.setPlaceholderText("请输入FTP密码")
        self.ftp_password_input.setEchoMode(QLineEdit.Password)  # 设置为密码输入模式
        ftp_layout.addRow("FTP密码:", self.ftp_password_input)

        self.ftp_port_input = QLineEdit()
        self.ftp_port_input.setPlaceholderText("请输入FTP端口")
        ftp_layout.addRow("FTP端口:", self.ftp_port_input)

        # 创建FTP连接测试按钮
        self.test_ftp_button = QPushButton("连接测试")
        self.test_ftp_button.clicked.connect(self.test_ftp_connection)
        ftp_layout.addRow("连接测试:", self.test_ftp_button)

        ftp_group.setLayout(ftp_layout)
        main_layout.addWidget(ftp_group)

        # 创建保存按钮
        self.save_button = QPushButton("保存")
        self.save_button.clicked.connect(self.save_config)
        main_layout.addWidget(self.save_button)

        # 设置中心部件的布局
        self.setLayout(main_layout)

        # 加载保存的配置
        self.load_saved_config()

    def save_config(self):
        """保存配置，在配置页面点击保存按钮时调用"""
        try:
            # 连接到SQLite数据库（如果数据库不存在，则会自动创建）
            # 相对于main.py，data.db的路径为./db/data.db
            connection, cursor = connect_sql()
            logger().info("[configPage-save_config]-连接到SQLite数据库成功")

            # 创建配置表
            create_config_table(cursor)

            # 初始化变量
            values = []
            placeholders = []

            # URL 和 AppID 总是插入
            values.append(self.url_input.text())
            placeholders.append('?')
            values.append(self.appid_input.text())
            placeholders.append('?')

            # AppKey 加密并插入
            appkey = self.appkey_input.text()
            if appkey:
                key_for_appkey = get_random_bytes(16).hex()
                new_appkey = encrypt_password(appkey, bytes.fromhex(key_for_appkey)).hex()
                values.extend([new_appkey, key_for_appkey])
                placeholders.extend(['?', '?'])
            else:
                values.extend(['', ''])  # 占位符，用于保持SQL语句结构一致

            # From Email 加密并插入
            from_email_password = self.from_email_password_input.text()
            if from_email_password:
                key_for_email_password = get_random_bytes(16).hex()
                new_from_email_password = encrypt_password(from_email_password,
                                                           bytes.fromhex(key_for_email_password)).hex()
                values.extend([self.from_email_input.text(), new_from_email_password, key_for_email_password])
                placeholders.extend(['?', '?', '?'])
            else:
                values.extend(['', '', ''])  # 占位符，用于保持SQL语句结构一致

            # SMTP Server 和 SMTP Port 总是插入
            values.append(self.smtp_server_input.text())
            placeholders.append('?')
            values.append(self.smtp_port_input.text())
            placeholders.append('?')

            # To Email 总是插入
            values.append(self.to_email_input.text())
            placeholders.append('?')

            # FTP Host, FTP User, FTP Password 加密并插入
            ftp_password = self.ftp_password_input.text()
            if ftp_password:
                key_for_ftp_password = get_random_bytes(16).hex()
                new_ftp_password = encrypt_password(ftp_password, bytes.fromhex(key_for_ftp_password)).hex()
                values.extend(
                    [self.ftp_host_input.text(), self.ftp_user_input.text(), new_ftp_password, key_for_ftp_password,
                     self.ftp_port_input.text()])
                placeholders.extend(['?', '?', '?', '?', '?'])
            else:
                values.extend(['', '', '', '', ''])  # 占位符，用于保持SQL语句结构一致

            # 构建SQL语句
            sql = f'''
                INSERT INTO Config (url, appid, appkey, key_for_appkey, from_email, from_email_password, key_for_email_password, smtp_server, smtp_port, to_email, ftp_host, ftp_user, ftp_password, key_for_ftp_password, ftp_port)
                VALUES ({', '.join(placeholders)})
            '''

            # 执行SQL语句
            cursor.execute(sql, values)
            logger().info("[configPage-save_config]-插入新的配置数据成功")

            # 提交事务
            connection.commit()
            logger().info("[configPage-save_config]-提交数据库事务成功")

            # 关闭连接
            connection.close()
            logger().info("[configPage-save_config]-关闭数据库连接成功")

            QMessageBox.information(self, "成功", "配置已保存")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 配置已保存")
            logger().info("[configPage-save_config]-配置已保存")

        except sqlite3.Error as e:
            QMessageBox.critical(self, "错误", f"保存配置时出错: {e}")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 保存配置时出错: {e}")
            logger().error(f"[configPage-save_config]-保存配置时出错: {e}")

    def load_saved_config(self):
        """加载保存的配置，在配置页面加载时调用显示上次保存的配置"""
        try:
            # 连接到SQLite数据库
            connection, cursor = connect_sql()
            logger().info("[configPage-load_saved_config]-连接到SQLite数据库成功")

            # 查询最新的配置数据
            cursor.execute("SELECT * FROM Config ORDER BY id DESC LIMIT 1")
            config = cursor.fetchone()

            if config:
                self.url_input.setText(config[1])
                self.appid_input.setText(config[2])
                # self.appkey_input.setText(config[3])  # 输入框不显示内容，所以注释掉
                self.from_email_input.setText(config[5])
                # self.from_email_password_input.setText(config[6])  # 输入框不显示内容，所以注释掉
                self.smtp_server_input.setText(config[8])
                self.smtp_port_input.setText(config[9])
                self.to_email_input.setText(config[10])
                self.ftp_host_input.setText(config[11])
                self.ftp_user_input.setText(config[12])
                # self.ftp_password_input.setText(config[13])  # 输入框不显示内容，所以注释掉
                self.ftp_port_input.setText(config[15])

            # 关闭连接
            connection.close()
            logger().info("[configPage-load_saved_config]-关闭数据库连接成功")

        except sqlite3.Error as e:
            QMessageBox.critical(self, "错误", f"加载配置时出错: {e}")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 加载配置时出错: {e}")
            logger().error(f"[configPage-load_saved_config]-加载配置时出错: {e}")

    def test_email(self):

        try:
            # 连接数据库获取配置信息
            connection, cursor = connect_sql()
            logger().info("[configPage-test_email]-连接到SQLite数据库成功")

            # 查询发件邮箱密码和key
            result = cursor.execute("SELECT from_email_password, key_for_email_password FROM Config").fetchone()

            # 获取加密后的发件邮箱密码和key并转换为字节格式
            encrypted_from_email_password = bytes.fromhex(result[0])
            key_for_email_password = bytes.fromhex(result[1])

            cursor.close()  # 关闭游标
            connection.close()  # 关闭数据库连接
            logger().info("[configPage-test_email]-关闭数据库连接成功")

            # 解密密码
            from_email_password = decrypt_password(encrypted_from_email_password, key_for_email_password)
            logger().info("[configPage-test_email]-解密发件邮箱密码成功")
            logger().info(f"[configPage-test_email]-发件邮箱密码: {from_email_password}")

            from_email = self.from_email_input.text()
            smtp_server = self.smtp_server_input.text()
            smtp_port = int(self.smtp_port_input.text())
            to_email = self.to_email_input.text()

            if not all([from_email, from_email_password, smtp_server, smtp_port, to_email]):
                QMessageBox.warning(self, "警告", "请填写所有邮箱配置项")
                self.log_text_edit.appendPlainText(
                    f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 未填写所有邮箱配置项")
                logger().warning("[configPage-test_email]-未填写所有邮箱配置项")
                return

            # 创建邮件内容
            message = MIMEMultipart()
            message['From'] = from_email
            message['To'] = to_email
            message['Subject'] = "测试邮件"
            body = "这是一封测试邮件，用于验证邮箱配置是否正确。"
            message.attach(MIMEText(body, 'plain'))

            # 连接到SMTP服务器并发送邮件
            with smtplib.SMTP_SSL(smtp_server, smtp_port) as server:
                server.login(from_email, from_email_password)
                logger().info("[configPage-test_email]-连接到SMTP服务器成功")
                server.sendmail(from_email, to_email, message.as_string())
                logger().info("[configPage-test_email]-发送测试邮件成功")

            QMessageBox.information(self, "成功", "测试邮件已发送")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 测试邮件已发送")

        except Exception as e:
            QMessageBox.critical(self, "错误", f"发送测试邮件时出错: {e}")
            self.log_text_edit.appendPlainText(
                f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 发送测试邮件时出错: {e}")
            logger().error(f"[configPage-test_email]-发送测试邮件时出错: {e}")

    def test_ftp_connection(self):
        try:
            ftp_host = self.ftp_host_input.text()
            ftp_user = self.ftp_user_input.text()
            ftp_password = self.ftp_password_input.text()
            ftp_port = int(self.ftp_port_input.text()) if self.ftp_port_input.text() else 21  # 默认端口为21

            if not all([ftp_host, ftp_user, ftp_password]):
                QMessageBox.warning(self, "警告", "请填写所有FTP配置项")
                self.log_text_edit.appendPlainText(
                    f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: 未填写所有FTP配置项")
                return

            ftp_server = "ftp_host:ftp_port".replace("ftp_host", ftp_host).replace("ftp_port", str(ftp_port))

            # 连接到FTP服务器
            with ftplib.FTP_TLS(ftp_server, ftp_user, ftp_password) as ftp:
                ftp.prot_p()  # 启用安全数据连接
                ftp.auth()
                ftp.pwd()  # 获取当前目录以验证连接

            QMessageBox.information(self, "成功", "FTP连接测试成功")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: FTP连接测试成功")

        except Exception as e:
            QMessageBox.critical(self, "错误", f"FTP连接测试失败: {e}")
            self.log_text_edit.appendPlainText(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: FTP连接测试失败: {e}")
